using System;
using System.ComponentModel;
using System.Data;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using Lucene.Linq.Mapping;
using Lucene.Linq.VSTests.Properties;
using Lucene.Linq.Search;
using System.Data.Entity;

namespace Lucene.Linq.VSTests.Data.LinqToSql
{
    /// <summary>
    /// This data context only has 1 table type decorated with [Document]. 
    /// This is used to test partially indexable Data Contexts.
    /// </summary>
    [Database(Name = "Northwind")]
    public partial class NorthwindDataContext : DataContext
    {
        #region Fields

        private static readonly MappingSource mappingSource = new AttributeMappingSource();

        #endregion

        #region Extensibility Method Definitions

        partial void OnCreated();
        partial void InsertCustomer(Customer instance);
        partial void UpdateCustomer(Customer instance);
        partial void DeleteCustomer(Customer instance);
        partial void InsertOrder(Order instance);
        partial void UpdateOrder(Order instance);
        partial void DeleteOrder(Order instance);

        #endregion

        #region Constructors

        static NorthwindDataContext()
        {
        }

        public NorthwindDataContext(string connection) :
            base(connection, mappingSource)
        {
            OnCreated();
        }

        public NorthwindDataContext(IDbConnection connection) :
            base(connection, mappingSource)
        {
            OnCreated();
        }

        public NorthwindDataContext(string connection, MappingSource mappingSource) :
            base(connection, mappingSource)
        {
            OnCreated();
        }

        public NorthwindDataContext(IDbConnection connection, MappingSource mappingSource) :
            base(connection, mappingSource)
        {
            OnCreated();
        }

        public NorthwindDataContext() :
            base((string) Settings.Default.NorthwindConnectionString, mappingSource)
        {
            OnCreated();
        }

        #endregion

        #region Properties

        public Table<Customer> Customers
        {
            get { return GetTable<Customer>(); }
        }


        public Table<Order> Orders
        {
            get { return GetTable<Order>(); }
        }

        #endregion
    }

    [Table(Name = "dbo.Orders")]
    public partial class Order : IIndexable, INotifyPropertyChanging, INotifyPropertyChanged
    {
        #region Fields

        private static readonly PropertyChangingEventArgs emptyChangingEventArgs =
            new PropertyChangingEventArgs(String.Empty);

        private EntityRef<Customer> _Customer;

        private string _CustomerID;
        private int? _EmployeeID;
        private decimal? _Freight;
        private DateTime? _OrderDate;
        private int _OrderID;
        private DateTime? _RequiredDate;
        private string _ShipAddress;
        private string _ShipCity;
        private string _ShipCountry;
        private string _ShipName;
        private string _ShipPostalCode;
        private string _ShipRegion;
        private int? _ShipVia;
        private DateTime? _ShippedDate;

        #endregion

        #region Extensibility Method Definitions

        partial void OnLoaded();
        partial void OnValidate();
        partial void OnCreated();
        partial void OnOrderIDChanging(int value);
        partial void OnOrderIDChanged();
        partial void OnCustomerIDChanging(string value);
        partial void OnCustomerIDChanged();
        partial void OnEmployeeIDChanging(int? value);
        partial void OnEmployeeIDChanged();
        partial void OnOrderDateChanging(DateTime? value);
        partial void OnOrderDateChanged();
        partial void OnRequiredDateChanging(DateTime? value);
        partial void OnRequiredDateChanged();
        partial void OnShippedDateChanging(DateTime? value);
        partial void OnShippedDateChanged();
        partial void OnShipViaChanging(int? value);
        partial void OnShipViaChanged();
        partial void OnFreightChanging(decimal? value);
        partial void OnFreightChanged();
        partial void OnShipNameChanging(string value);
        partial void OnShipNameChanged();
        partial void OnShipAddressChanging(string value);
        partial void OnShipAddressChanged();
        partial void OnShipCityChanging(string value);
        partial void OnShipCityChanged();
        partial void OnShipRegionChanging(string value);
        partial void OnShipRegionChanged();
        partial void OnShipPostalCodeChanging(string value);
        partial void OnShipPostalCodeChanged();
        partial void OnShipCountryChanging(string value);
        partial void OnShipCountryChanged();

        #endregion

        #region Constructors

        public Order()
        {
            OnCreated();
            _Customer = default(EntityRef<Customer>);
        }

        #endregion

        #region Properties

        [Field(FieldIndex.Tokenized, FieldStore.Yes)]
        [Column(Storage = "_OrderID", AutoSync = AutoSync.OnInsert, DbType = "Int NOT NULL IDENTITY",
            IsPrimaryKey = true, IsDbGenerated = true)]
        public int OrderID
        {
            get { return _OrderID; }
            set
            {
                if ((_OrderID != value))
                {
                    OnOrderIDChanging(value);
                    SendPropertyChanging();
                    _OrderID = value;
                    SendPropertyChanged("OrderID");
                    OnOrderIDChanged();
                }
            }
        }

        [Field(FieldIndex.Tokenized, FieldStore.Yes)]
        [Column(Storage = "_CustomerID", DbType = "NChar(5)")]
        public string CustomerID
        {
            get { return _CustomerID; }
            set
            {
                if ((_CustomerID != value))
                {
                    if (_Customer.HasLoadedOrAssignedValue)
                    {
                        throw new ForeignKeyReferenceAlreadyHasValueException();
                    }
                    OnCustomerIDChanging(value);
                    SendPropertyChanging();
                    _CustomerID = value;
                    SendPropertyChanged("CustomerID");
                    OnCustomerIDChanged();
                }
            }
        }

        [Column(Storage = "_EmployeeID", DbType = "Int")]
        public int? EmployeeID
        {
            get { return _EmployeeID; }
            set
            {
                if ((_EmployeeID != value))
                {
                    OnEmployeeIDChanging(value);
                    SendPropertyChanging();
                    _EmployeeID = value;
                    SendPropertyChanged("EmployeeID");
                    OnEmployeeIDChanged();
                }
            }
        }

        [Column(Storage = "_OrderDate", DbType = "DateTime")]
        public DateTime? OrderDate
        {
            get { return _OrderDate; }
            set
            {
                if ((_OrderDate != value))
                {
                    OnOrderDateChanging(value);
                    SendPropertyChanging();
                    _OrderDate = value;
                    SendPropertyChanged("OrderDate");
                    OnOrderDateChanged();
                }
            }
        }

        [Column(Storage = "_RequiredDate", DbType = "DateTime")]
        public DateTime? RequiredDate
        {
            get { return _RequiredDate; }
            set
            {
                if ((_RequiredDate != value))
                {
                    OnRequiredDateChanging(value);
                    SendPropertyChanging();
                    _RequiredDate = value;
                    SendPropertyChanged("RequiredDate");
                    OnRequiredDateChanged();
                }
            }
        }

        [Column(Storage = "_ShippedDate", DbType = "DateTime")]
        public DateTime? ShippedDate
        {
            get { return _ShippedDate; }
            set
            {
                if ((_ShippedDate != value))
                {
                    OnShippedDateChanging(value);
                    SendPropertyChanging();
                    _ShippedDate = value;
                    SendPropertyChanged("ShippedDate");
                    OnShippedDateChanged();
                }
            }
        }

        [Column(Storage = "_ShipVia", DbType = "Int")]
        public int? ShipVia
        {
            get { return _ShipVia; }
            set
            {
                if ((_ShipVia != value))
                {
                    OnShipViaChanging(value);
                    SendPropertyChanging();
                    _ShipVia = value;
                    SendPropertyChanged("ShipVia");
                    OnShipViaChanged();
                }
            }
        }

        [Column(Storage = "_Freight", DbType = "Money")]
        public decimal? Freight
        {
            get { return _Freight; }
            set
            {
                if ((_Freight != value))
                {
                    OnFreightChanging(value);
                    SendPropertyChanging();
                    _Freight = value;
                    SendPropertyChanged("Freight");
                    OnFreightChanged();
                }
            }
        }

        [Field(FieldIndex.Tokenized, FieldStore.Yes, IsDefault = true)]
        [Column(Storage = "_ShipName", DbType = "NVarChar(40)")]
        public string ShipName
        {
            get { return _ShipName; }
            set
            {
                if ((_ShipName != value))
                {
                    OnShipNameChanging(value);
                    SendPropertyChanging();
                    _ShipName = value;
                    SendPropertyChanged("ShipName");
                    OnShipNameChanged();
                }
            }
        }

        [Field(FieldIndex.Tokenized, FieldStore.Yes)]
        [Column(Storage = "_ShipAddress", DbType = "NVarChar(60)")]
        public string ShipAddress
        {
            get { return _ShipAddress; }
            set
            {
                if ((_ShipAddress != value))
                {
                    OnShipAddressChanging(value);
                    SendPropertyChanging();
                    _ShipAddress = value;
                    SendPropertyChanged("ShipAddress");
                    OnShipAddressChanged();
                }
            }
        }

        [Field(FieldIndex.Tokenized, FieldStore.Yes)]
        [Column(Storage = "_ShipCity", DbType = "NVarChar(15)")]
        public string ShipCity
        {
            get { return _ShipCity; }
            set
            {
                if ((_ShipCity != value))
                {
                    OnShipCityChanging(value);
                    SendPropertyChanging();
                    _ShipCity = value;
                    SendPropertyChanged("ShipCity");
                    OnShipCityChanged();
                }
            }
        }

        [Column(Storage = "_ShipRegion", DbType = "NVarChar(15)")]
        public string ShipRegion
        {
            get { return _ShipRegion; }
            set
            {
                if ((_ShipRegion != value))
                {
                    OnShipRegionChanging(value);
                    SendPropertyChanging();
                    _ShipRegion = value;
                    SendPropertyChanged("ShipRegion");
                    OnShipRegionChanged();
                }
            }
        }

        [Column(Storage = "_ShipPostalCode", DbType = "NVarChar(10)")]
        public string ShipPostalCode
        {
            get { return _ShipPostalCode; }
            set
            {
                if ((_ShipPostalCode != value))
                {
                    OnShipPostalCodeChanging(value);
                    SendPropertyChanging();
                    _ShipPostalCode = value;
                    SendPropertyChanged("ShipPostalCode");
                    OnShipPostalCodeChanged();
                }
            }
        }

        [Field(FieldIndex.Tokenized, FieldStore.Yes)]
        [Column(Storage = "_ShipCountry", DbType = "NVarChar(15)")]
        public string ShipCountry
        {
            get { return _ShipCountry; }
            set
            {
                if ((_ShipCountry != value))
                {
                    OnShipCountryChanging(value);
                    SendPropertyChanging();
                    _ShipCountry = value;
                    SendPropertyChanged("ShipCountry");
                    OnShipCountryChanged();
                }
            }
        }

        //[Association(Name = "Customer_Order", Storage = "_Customer", ThisKey = "CustomerID", IsForeignKey = true)]
        //public Customer Customer
        //{
        //  get
        //  {
        //    return this._Customer.Entity;
        //  }
        //  set
        //  {
        //    Customer previousValue = this._Customer.Entity;
        //    if (((previousValue != value)
        //          || (this._Customer.HasLoadedOrAssignedValue == false)))
        //    {
        //      this.SendPropertyChanging();
        //      if ((previousValue != null))
        //      {
        //        this._Customer.Entity = null;
        //        previousValue.Orders.Remove(this);
        //      }
        //      this._Customer.Entity = value;
        //      if ((value != null))
        //      {
        //        value.Orders.Add(this);
        //        this._CustomerID = value.CustomerID;
        //      }
        //      else
        //      {
        //        this._CustomerID = default(string);
        //      }
        //      this.SendPropertyChanged("Customer");
        //    }
        //  }
        //}

        #endregion

        #region Methods

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region INotifyPropertyChanging Members

        public event PropertyChangingEventHandler PropertyChanging;

        #endregion

        protected virtual void SendPropertyChanging()
        {
            if ((PropertyChanging != null))
            {
                PropertyChanging(this, emptyChangingEventArgs);
            }
        }

        protected virtual void SendPropertyChanged(String propertyName)
        {
            if ((PropertyChanged != null))
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
    }

    [Document]
    [Table(Name = "dbo.Customers")]
    public partial class Customer : IIndexable, INotifyPropertyChanging, INotifyPropertyChanged
    {
        #region Fields

        private static readonly PropertyChangingEventArgs emptyChangingEventArgs =
            new PropertyChangingEventArgs(String.Empty);

        private string _Address;
        private string _City;

        private string _CompanyName;
        private string _ContactName;
        private string _ContactTitle;
        private string _Country;
        private string _CustomerID;
        private string _Fax;
        private EntitySet<Order> _Orders;
        private string _Phone;
        private string _PostalCode;
        private string _Region;

        #endregion

        #region Extensibility Method Definitions

        partial void OnLoaded();
        partial void OnValidate();
        partial void OnCreated();
        partial void OnCustomerIDChanging(string value);
        partial void OnCustomerIDChanged();
        partial void OnCompanyNameChanging(string value);
        partial void OnCompanyNameChanged();
        partial void OnContactNameChanging(string value);
        partial void OnContactNameChanged();
        partial void OnContactTitleChanging(string value);
        partial void OnContactTitleChanged();
        partial void OnAddressChanging(string value);
        partial void OnAddressChanged();
        partial void OnCityChanging(string value);
        partial void OnCityChanged();
        partial void OnRegionChanging(string value);
        partial void OnRegionChanged();
        partial void OnPostalCodeChanging(string value);
        partial void OnPostalCodeChanged();
        partial void OnCountryChanging(string value);
        partial void OnCountryChanged();
        partial void OnPhoneChanging(string value);
        partial void OnPhoneChanged();
        partial void OnFaxChanging(string value);
        partial void OnFaxChanged();

        #endregion

        #region Constructors

        public Customer()
        {
            OnCreated();
            //this._Orders = new EntitySet<Order>(new Action<Order>(this.attach_Orders), new Action<Order>(this.detach_Orders));
        }

        #endregion

        #region Properties

        public DateTime StartDate { get; set; }

        [Field(FieldIndex.Tokenized, FieldStore.Yes)]
        [Column(Storage = "_CustomerID", DbType = "NChar(5) NOT NULL", CanBeNull = false, IsPrimaryKey = true)]
        public string CustomerID
        {
            get { return _CustomerID; }
            set
            {
                if ((_CustomerID != value))
                {
                    OnCustomerIDChanging(value);
                    SendPropertyChanging();
                    _CustomerID = value;
                    SendPropertyChanged("CustomerID");
                    OnCustomerIDChanged();
                }
            }
        }

        [Field(FieldIndex.Tokenized, FieldStore.Yes, IsDefault = true)]
        [Column(Storage = "_CompanyName", DbType = "NVarChar(40) NOT NULL", CanBeNull = false)]
        public string CompanyName
        {
            get { return _CompanyName; }
            set
            {
                if ((_CompanyName != value))
                {
                    OnCompanyNameChanging(value);
                    SendPropertyChanging();
                    _CompanyName = value;
                    SendPropertyChanged("CompanyName");
                    OnCompanyNameChanged();
                }
            }
        }

        [Field(FieldIndex.Tokenized, FieldStore.Yes, Name = "ContactName")]
        [Column(Storage = "_ContactName", DbType = "NVarChar(30)")]
        public string ContactName
        {
            get { return _ContactName; }
            set
            {
                if ((_ContactName != value))
                {
                    OnContactNameChanging(value);
                    SendPropertyChanging();
                    _ContactName = value;
                    SendPropertyChanged("ContactName");
                    OnContactNameChanged();
                }
            }
        }

        [Field(FieldIndex.Tokenized, FieldStore.Yes)]
        [Column(Storage = "_ContactTitle", DbType = "NVarChar(30)")]
        public string ContactTitle
        {
            get { return _ContactTitle; }
            set
            {
                if ((_ContactTitle != value))
                {
                    OnContactTitleChanging(value);
                    SendPropertyChanging();
                    _ContactTitle = value;
                    SendPropertyChanged("ContactTitle");
                    OnContactTitleChanged();
                }
            }
        }

        [Column(Storage = "_Address", DbType = "NVarChar(60)")]
        public string Address
        {
            get { return _Address; }
            set
            {
                if ((_Address != value))
                {
                    OnAddressChanging(value);
                    SendPropertyChanging();
                    _Address = value;
                    SendPropertyChanged("Address");
                    OnAddressChanged();
                }
            }
        }

        [Column(Storage = "_City", DbType = "NVarChar(15)")]
        public string City
        {
            get { return _City; }
            set
            {
                if ((_City != value))
                {
                    OnCityChanging(value);
                    SendPropertyChanging();
                    _City = value;
                    SendPropertyChanged("City");
                    OnCityChanged();
                }
            }
        }

        [Column(Storage = "_Region", DbType = "NVarChar(15)")]
        public string Region
        {
            get { return _Region; }
            set
            {
                if ((_Region != value))
                {
                    OnRegionChanging(value);
                    SendPropertyChanging();
                    _Region = value;
                    SendPropertyChanged("Region");
                    OnRegionChanged();
                }
            }
        }

        [Column(Storage = "_PostalCode", DbType = "NVarChar(10)")]
        public string PostalCode
        {
            get { return _PostalCode; }
            set
            {
                if ((_PostalCode != value))
                {
                    OnPostalCodeChanging(value);
                    SendPropertyChanging();
                    _PostalCode = value;
                    SendPropertyChanged("PostalCode");
                    OnPostalCodeChanged();
                }
            }
        }

        [Column(Storage = "_Country", DbType = "NVarChar(15)")]
        public string Country
        {
            get { return _Country; }
            set
            {
                if ((_Country != value))
                {
                    OnCountryChanging(value);
                    SendPropertyChanging();
                    _Country = value;
                    SendPropertyChanged("Country");
                    OnCountryChanged();
                }
            }
        }

        [Column(Storage = "_Phone", DbType = "NVarChar(24)")]
        public string Phone
        {
            get { return _Phone; }
            set
            {
                if ((_Phone != value))
                {
                    OnPhoneChanging(value);
                    SendPropertyChanging();
                    _Phone = value;
                    SendPropertyChanged("Phone");
                    OnPhoneChanged();
                }
            }
        }

        [Column(Storage = "_Fax", DbType = "NVarChar(24)")]
        public string Fax
        {
            get { return _Fax; }
            set
            {
                if ((_Fax != value))
                {
                    OnFaxChanging(value);
                    SendPropertyChanging();
                    _Fax = value;
                    SendPropertyChanged("Fax");
                    OnFaxChanged();
                }
            }
        }

        //[Association(Name = "Customer_Order", Storage = "_Orders", OtherKey = "CustomerID")]
        //public EntitySet<Order> Orders
        //{
        //  get
        //  {
        //    return this._Orders;
        //  }
        //  set
        //  {
        //    this._Orders.Assign(value);
        //  }
        //}

        #endregion

        #region Events

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region INotifyPropertyChanging Members

        public event PropertyChangingEventHandler PropertyChanging;

        #endregion

        #endregion

        #region Methods

        protected virtual void SendPropertyChanging()
        {
            if ((PropertyChanging != null))
            {
                PropertyChanging(this, emptyChangingEventArgs);
            }
        }

        protected virtual void SendPropertyChanged(String propertyName)
        {
            if ((PropertyChanged != null))
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        //private void attach_Orders(Order entity)
        //{
        //  this.SendPropertyChanging();
        //  entity.Customer = this;
        //  this.SendPropertyChanged("Orders");
        //}

        //private void detach_Orders(Order entity)
        //{
        //  this.SendPropertyChanging();
        //  entity.Customer = null;
        //  this.SendPropertyChanged("Orders");
        //}

        #endregion
    }
}


namespace Lucene.Linq.VSTests.Data.CodeFirst
{
    //
    // POCO Model Classes
    //
    public class Order : IIndexable
    {

        [Field(FieldIndex.Tokenized, FieldStore.Yes)]
        public int OrderID
        {
            get;
            set;
        }

        [Field(FieldIndex.Tokenized, FieldStore.Yes)]
        public string CustomerID
        {
            get;
            set;
        }


        public int? EmployeeID
        {
            get;
            set;
        }

        public DateTime? OrderDate
        {
            get;
            set;
        }

        public DateTime? RequiredDate
        {
            get;
            set;
        }

        public DateTime? ShippedDate
        {
            get;
            set;
        }

        public int? ShipVia
        {
            get;
            set;
        }

        public decimal? Freight
        {
            get;
            set;
        }

        [Field(FieldIndex.Tokenized, FieldStore.Yes, IsDefault = true)]
        public string ShipName
        {
            get;
            set;
        }

        [Field(FieldIndex.Tokenized, FieldStore.Yes)]
        public string ShipAddress
        {
            get;
            set;
        }

        [Field(FieldIndex.Tokenized, FieldStore.Yes)]
        public string ShipCity
        {
            get;
            set;
        }

        public string ShipRegion
        {
            get;
            set;
        }

        public string ShipPostalCode
        {
            get;
            set;
        }

        [Field(FieldIndex.Tokenized, FieldStore.Yes)]
        public string ShipCountry
        {
            get;
            set;
        }

    }

    [Document]
    public class Customer : IIndexable
    {

        #region Properties

        public DateTime StartDate { get; set; }

        [Field(FieldIndex.Tokenized, FieldStore.Yes)]
        public string CustomerID
        {
            get;
            set;
        }

        [Field(FieldIndex.Tokenized, FieldStore.Yes, IsDefault = true)]
        public string CompanyName
        {
            get;
            set;
        }

        [Field(FieldIndex.Tokenized, FieldStore.Yes, Name = "ContactName")]
        public string ContactName
        {
            get;
            set;
        }

        [Field(FieldIndex.Tokenized, FieldStore.Yes)]
        public string ContactTitle
        {
            get;
            set;
        }

        public string Address
        {
            get;
            set;
        }

        public string City
        {
            get;
            set;
        }

        public string Region
        {
            get;
            set;
        }

        public string PostalCode
        {
            get;
            set;
        }

        public string Country
        {
            get;
            set;
        }

        public string Phone
        {
            get;
            set;
        }

        public string Fax
        {
            get;
            set;
        }

        #endregion


    }

    //
    // Northwind EF Code First Context Class
    //

    public class NorthwindDbContext : DbContext
    {
        public DbSet<Order> Orders { get; set; }
        public DbSet<Customer> Customers { get; set; }
    }


    [Document]
    public class FakeTable : IIndexable
    {
        
    }
}